package com.example.lock;

import java.util.concurrent.TimeUnit;

import lombok.EqualsAndHashCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.data.redis.core.StringRedisTemplate;

@EqualsAndHashCode
public class ShardRabbitLock {
    private static final Logger log = LoggerFactory.getLogger(ShardRabbitLock.class);
    private String queueNamePrefix;
    private int size;
    private int num;
    private MessageListenerContainer container;
    private StringRedisTemplate redisTemplate;
    private long timeout = 10L;
    private String instanceId;

    public boolean freshLock() {
        return this.redisTemplate.opsForValue().setIfPresent(this.key(), this.instanceId, this.timeout, TimeUnit.SECONDS);
    }

    public boolean tryLock() {
        return this.tryLock(this.timeout);
    }

    public boolean tryLock(long timeout) {
        boolean result = this.redisTemplate.opsForValue().setIfAbsent(this.key(), this.instanceId, timeout, TimeUnit.SECONDS);
        if (result) {
            log.info("tryLock take lock:{}", this.key());
            this.start();
        }

        return result;
    }

    public boolean releaseLock() {
        boolean result = false;
        if (this.hasLock()) {
            log.info("start to release Lock lock:{}", this.key());
            this.stop();
            result = this.redisTemplate.delete(this.key());
            log.info("release Lock done lock:{},result:{}", this.key(), result);
        }

        return result;
    }

    public void checkLock() {
        if (this.hasLock()) {
            this.start();
        } else {
            this.stop();
        }

    }

    public void stop() {
        if (this.container.isRunning()) {
            log.info("stopping MessageListenerContainer, key:{}", this.key());
            this.container.stop();
        }

    }

    public void start() {
        if (!this.container.isRunning()) {
            log.info("starting MessageListenerContainer, key:{}", this.key());
            this.container.start();
        }

    }

    public boolean hasLock() {
        String value = (String)this.redisTemplate.opsForValue().get(this.key());
        return this.instanceId.equals(value);
    }

    public String key() {
        return "SHARD_RABBIT_LOCK_" + this.queueNamePrefix + "_" + this.num;
    }

    public ShardRabbitLock() {
    }

    public String getQueueNamePrefix() {
        return this.queueNamePrefix;
    }

    public int getSize() {
        return this.size;
    }

    public int getNum() {
        return this.num;
    }

    public MessageListenerContainer getContainer() {
        return this.container;
    }

    public StringRedisTemplate getRedisTemplate() {
        return this.redisTemplate;
    }

    public long getTimeout() {
        return this.timeout;
    }

    public String getInstanceId() {
        return this.instanceId;
    }

    public void setQueueNamePrefix(String queueNamePrefix) {
        this.queueNamePrefix = queueNamePrefix;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void setContainer(MessageListenerContainer container) {
        this.container = container;
    }

    public void setRedisTemplate(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public void setInstanceId(String instanceId) {
        this.instanceId = instanceId;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof ShardRabbitLock)) {
            return false;
        } else {
            ShardRabbitLock other = (ShardRabbitLock)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label71: {
                    Object this$queueNamePrefix = this.getQueueNamePrefix();
                    Object other$queueNamePrefix = other.getQueueNamePrefix();
                    if (this$queueNamePrefix == null) {
                        if (other$queueNamePrefix == null) {
                            break label71;
                        }
                    } else if (this$queueNamePrefix.equals(other$queueNamePrefix)) {
                        break label71;
                    }

                    return false;
                }

                if (this.getSize() != other.getSize()) {
                    return false;
                } else if (this.getNum() != other.getNum()) {
                    return false;
                } else {
                    Object this$container = this.getContainer();
                    Object other$container = other.getContainer();
                    if (this$container == null) {
                        if (other$container != null) {
                            return false;
                        }
                    } else if (!this$container.equals(other$container)) {
                        return false;
                    }

                    label54: {
                        Object this$redisTemplate = this.getRedisTemplate();
                        Object other$redisTemplate = other.getRedisTemplate();
                        if (this$redisTemplate == null) {
                            if (other$redisTemplate == null) {
                                break label54;
                            }
                        } else if (this$redisTemplate.equals(other$redisTemplate)) {
                            break label54;
                        }

                        return false;
                    }

                    if (this.getTimeout() != other.getTimeout()) {
                        return false;
                    } else {
                        Object this$instanceId = this.getInstanceId();
                        Object other$instanceId = other.getInstanceId();
                        if (this$instanceId == null) {
                            if (other$instanceId != null) {
                                return false;
                            }
                        } else if (!this$instanceId.equals(other$instanceId)) {
                            return false;
                        }

                        return true;
                    }
                }
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof ShardRabbitLock;
    }

//    public int hashCode() {
//        int PRIME = true;
//        int result = 1;
//        Object $queueNamePrefix = this.getQueueNamePrefix();
//        int result = result * 59 + ($queueNamePrefix == null ? 43 : $queueNamePrefix.hashCode());
//        result = result * 59 + this.getSize();
//        result = result * 59 + this.getNum();
//        Object $container = this.getContainer();
//        result = result * 59 + ($container == null ? 43 : $container.hashCode());
//        Object $redisTemplate = this.getRedisTemplate();
//        result = result * 59 + ($redisTemplate == null ? 43 : $redisTemplate.hashCode());
//        long $timeout = this.getTimeout();
//        result = result * 59 + (int)($timeout >>> 32 ^ $timeout);
//        Object $instanceId = this.getInstanceId();
//        result = result * 59 + ($instanceId == null ? 43 : $instanceId.hashCode());
//        return result;
//    }

    public String toString() {
        return "ShardRabbitLock(queueNamePrefix=" + this.getQueueNamePrefix() + ", size=" + this.getSize() + ", num=" + this.getNum() + ", container=" + this.getContainer() + ", redisTemplate=" + this.getRedisTemplate() + ", timeout=" + this.getTimeout() + ", instanceId=" + this.getInstanceId() + ")";
    }
}
